/*
 * Copyright 2016 Hannes Dorfmann.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.hannesdorfmann.mosby3.mvi;

import com.hannesdorfmann.mosby3.AbilityMviDelegate;
import com.hannesdorfmann.mosby3.AbilityMviDelegateImpl;
import com.hannesdorfmann.mosby3.MviDelegateCallback;
import com.hannesdorfmann.mosby3.mvp.MvpPresenter;
import com.hannesdorfmann.mosby3.mvp.MvpView;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
import ohos.utils.PacMap;

/**
 * <p>
 * This abstract class can be used to extend from to implement an Model-View-Intent pattern with
 * this activity as View and a {@link MviPresenter} to coordinate the View and the underlying
 * model (business logic).
 * </p>
 * <p>
 * Per default {@link ActivityMviDelegateImpl} is used which means the View is attached to the
 * presenter in {@link
 * Activity#onStart()}. You better initialize all your UI components before that, typically in
 * {@link Activity#onCreate(Bundle)}.
 * The view is detached from presenter in {@link
 * Activity#onStop()}
 * </p>
 *
 * @author Hannes Dorfmann
 */
public abstract class MviAbility<V extends MvpView, P extends MviPresenter<V, ?>>
    extends Ability implements MvpView, MviDelegateCallback<V, P> {

  private boolean isRestoringViewState = false;
  protected AbilityMviDelegate<V, P> mvpDelegate;

  /**
   * Instantiate a presenter instance
   *
   * @return The {@link MvpPresenter} for this viewState
   */
  public abstract P createPresenter();

  /**
   * Get the mvp delegate. This is internally used for creating presenter, attaching and detaching
   * viewState from presenter.
   *
   * <p><b>Please note that only one instance of mvp delegate should be used per Activity
   * instance</b>.
   * </p>
   *
   * <p>
   * Only override this method if you really know what you are doing.
   * </p>
   *
   * @return {@link AbilityMviDelegate}
   */
  protected AbilityMviDelegate<V, P> getMvpDelegate() {
    if (mvpDelegate == null) {
      mvpDelegate = new AbilityMviDelegateImpl<V, P>(this, this);
    }

    return mvpDelegate;
  }

  @Override public V getMvpView() {
    try {
      return (V) this;
    } catch (ClassCastException e) {
      String msg =
              "Couldn't cast the View to the corresponding View interface. Most likely you forgot to add \"Activity implements YourMviViewInterface\".";
      throw new RuntimeException(msg, e);
    }
  }

  @Override public void setRestoringViewState(boolean restoringViewState) {
    this.isRestoringViewState = restoringViewState;
  }

  protected boolean isRestoringViewState() {
    return isRestoringViewState;
  }

  @Override
  protected void onStart(Intent intent) {
    super.onStart(intent);
    getMvpDelegate().onStart(intent);
  }

  @Override
  protected void onStop() {
    super.onStop();
    getMvpDelegate().onStop();
  }

  @Override
  protected void onInactive() {
    super.onInactive();
    getMvpDelegate().onInactive();
  }

  @Override
  protected void onActive() {
    super.onActive();
    getMvpDelegate().onActive();
  }

  @Override
  protected void onBackground() {
    super.onBackground();
    getMvpDelegate().onBackground();
  }

  @Override
  protected void onForeground(Intent intent) {
    super.onForeground(intent);
    getMvpDelegate().onForeground(intent);
  }

  @Override
  protected void onPostActive() {
    super.onPostActive();
    getMvpDelegate().onPostActive();
  }

  @Override
  public void onSaveAbilityState(PacMap outState) {
    super.onSaveAbilityState(outState);
    getMvpDelegate().onSaveAbilityState(outState);
  }

}


